package org.kust.bbs.user.service.impl;

import org.apache.commons.lang3.RandomStringUtils;
import org.kust.bbs.common.ex.ServiceException;
import org.kust.bbs.common.utils.JwtUtils;
import org.kust.bbs.common.utils.MD5Utils;
import org.kust.bbs.common.web.State;
import org.kust.bbs.pojo.entity.User;
import org.kust.bbs.pojo.vo.RegisterVO;
import org.kust.bbs.pojo.vo.RetrievePasswordVO;
import org.kust.bbs.pojo.vo.UpdatePasswordVO;
import org.kust.bbs.pojo.vo.UserCodeLoginVO;
import org.kust.bbs.user.mapper.UserMapper;
import org.kust.bbs.user.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.net.InetAddress;
import java.time.LocalDateTime;

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    /**
     * 判断手机号是否合法
     *
     * @param paramString
     * @return
     */
    public static boolean isValidMobiNumber(String paramString) {
        String regex = "^1\\d{10}$";
        if (paramString.matches(regex)) {
            return true;
        }
        return false;
    }

    /**
     * 用户密码登录
     *
     * @param user
     * @param request
     * @return
     */
    @Override
    public String login(User user, HttpServletRequest request) {
        //用户信息
        User userInfo;

        //获取登录手机号和密码
        String phone = user.getPhone();
        String password = user.getPassword();

        //手机号和密码的非空判断
        if (phone == null || password == null) {
            throw new ServiceException(State.ERR_NOT_FOUND, "手机号和密码不能为空");
        }
        //判断是否为有效的手机号
        if (isValidMobiNumber(phone)) {
            //判断数据库是否有该账户
            if ((userInfo = userMapper.selectUser(phone)) == null) {
                throw new ServiceException(State.ERR_NOT_FOUND, "登录失败");
            }
        } else {
            throw new ServiceException(State.ERR_BAD_REQUEST, "该手机号不合法");
        }
        //判断密码是否正确
        //使用MD5方式密码加密,和数据库中加密后的值进行比较
        if (!(MD5Utils.MD5(password).equals(userInfo.getPassword()))) {
            throw new ServiceException(State.ERR_NOT_FOUND, "密码错误");
        }
        //判断用户是否被禁用
        if (userInfo.getIsEnable() == 0) {
            throw new ServiceException(State.ERR_BAD_REQUEST, "登录失败,账号被禁用");
        }

//        if(userMapper.selectIP(phone)==null){
//            userMapper.updateIP(getIpAddr(request),phone);
//        }else {
//            userMapper.updateIPIsNull(phone);
//            userMapper.updateIP(getIpAddr(request),phone);
//        }

        //用户登录次数更新
        userMapper.countLogin(phone);
        //更新登录时间
        userMapper.updateGmtLastLogin(LocalDateTime.now(), phone);

        //登录成功后,生成token字符串信息
        String jwtToken = JwtUtils.getJwtToken(userInfo.getId(), userInfo.getUsername());
        return jwtToken;
    }

    /**
     * 用户验证码登录
     *
     * @param userCodeLoginVO
     * @return
     */
    @Override
    public String codeLogin(UserCodeLoginVO userCodeLoginVO, HttpServletRequest request) {
        //保存用户信息
        User userInfo;

        //获取登录时的手机号和验证码
        String phone = userCodeLoginVO.getPhone();
        String code = userCodeLoginVO.getCode();

        //判断手机号和验证码不能为空
        if (phone == null || code == null) {
            throw new ServiceException(State.ERR_BAD_REQUEST, "手机号或验证码不能为空");
        }

        //检验手机号是否合法
        if (isValidMobiNumber(phone)) {
            //判断数据库是否有该账户
            if ((userInfo = userMapper.selectUser(phone)) == null) {
                throw new ServiceException(State.ERR_BAD_REQUEST, "该用户不存在");
            }
        } else {
            throw new ServiceException(State.ERR_BAD_REQUEST, "该手机号不合法");
        }

        //判断输入的验证码是否正确
        if (!code.equals(redisTemplate.opsForValue().get(phone))) {
            throw new ServiceException(State.ERR_BAD_REQUEST, "验证码错误");
        }

        //判断账号是否可用
        if (userInfo.getIsEnable() == 0) {
            throw new ServiceException(State.ERR_BAD_REQUEST, "该账户已被禁用");
        }

//        if(userMapper.selectIP(phone)==null){
//            userMapper.updateIP(getIpAddr(request),phone);
//        }else {
//            userMapper.updateIPIsNull(phone);
//            userMapper.updateIP(getIpAddr(request),phone);
//        }

        //用户登录次数更新
        userMapper.countLogin(phone);
        //更新登录时间
        userMapper.updateGmtLastLogin(LocalDateTime.now(), phone);

        //登录成功后,生成token字符串信息
        String jwtToken = JwtUtils.getJwtToken(userInfo.getId(), userInfo.getUsername());
        return jwtToken;
    }

    /**
     * 用户注册
     */
    @Override
    public void register(RegisterVO registerVo) {
        //获取注册信息
        String phone = registerVo.getPhone();
        String password = registerVo.getPassword();
        String code = registerVo.getCode();

        //手机号和密码的非空判断
        if (phone == null || password == null) {
            throw new ServiceException(State.ERR_NOT_FOUND, "手机号或密码不能为空");
        }

        //判断手机号是否存在
        if (userMapper.countPhone(phone) != null) {
            throw new ServiceException(State.ERR_BAD_REQUEST, "手机号已存在");
        }

        //判断验证码是否正确
        if (!code.equals(redisTemplate.opsForValue().get(phone))) {
            throw new ServiceException(State.ERR_BAD_REQUEST, "验证码错误");
        }

        //设置用户初始参数
        User user = new User();
        //设置手机号
        user.setPhone(phone);
        //密码加密
        user.setPassword(MD5Utils.MD5(registerVo.getPassword()));
        //设置账号默认启用
        user.setIsEnable(1);
        //设置随机默认用户名(八位随机英文字母大小写+"_"+四位随机数字)
        user.setUsername(RandomStringUtils.randomAlphabetic(8) + "_" + RandomStringUtils.randomNumeric(4));
        //设置默认个性标签
        user.setSignature("该用户还没有设置个性标签..........");
        //设置默认头像
        user.setAvatar("https://tse4-mm.cn.bing.net/th/id/OIP-C.OFX1slcEQjk1t4B-WKIe1AAAAA?w=150&h=150&c=7&r=0&o=5&dpr=1.1&pid=1.7");
        //设置注册时间
        user.setGmtCreate(LocalDateTime.now());
        //将用户信息插入数据库
        userMapper.insertUser(user);
    }

    /**
     * 根据token信息中用户id,获取用户信息
     *
     * @param userId
     * @return
     */
    @Override
    public User getUserInfoById(Integer userId) {
        User user = userMapper.getById(userId);
        return user;
    }

    /**
     * 用户修改密码
     *
     * @param updatePasswordVO
     * @return
     */
    @Override
    public String updatePassword(UpdatePasswordVO updatePasswordVO) {
        //保存用户信息
        User userInfo;
        //获取更改时的信息值
        String oldPassword = updatePasswordVO.getOldPassword();
        String newPassword = updatePasswordVO.getNewPassword();
        String phone = updatePasswordVO.getPhone();
        String code = updatePasswordVO.getCode();

        //获取用户的密码信息
        userInfo = userMapper.selectUser(phone);

        //判断手机号,旧密码和新密码是否为空
        if (oldPassword == null || newPassword == null || phone == null || code == null) {
            throw new ServiceException(State.ERR_NOT_FOUND, "手机号,旧密码,新密码和验证码都不能为空");
        }

        //判断是否为有效的手机号
        if (isValidMobiNumber(phone)) {
            //判断数据库是否有该账户
            if (userInfo == null) {
                throw new ServiceException(State.ERR_NOT_FOUND, "没有该账号,请先注册");
            }
        } else {
            throw new ServiceException(State.ERR_NOT_FOUND, "该手机号不合法");
        }

        //旧密码比对
        if (!(MD5Utils.MD5(oldPassword).equals(userInfo.getPassword()))) {
            throw new ServiceException(State.ERR_NOT_FOUND, "旧密码输入错误");
        }
        //新旧密码比对
        if (MD5Utils.MD5(newPassword).equals(userInfo.getPassword())) {
            throw new ServiceException(State.ERR_NOT_FOUND, "新密码不能与旧密码相同");
        }

        if (!(code.equals(redisTemplate.opsForValue().get(phone)))) {
            throw new ServiceException(State.ERR_NOT_FOUND, "验证码输入错误");
        }
        //更新新密码
        userMapper.updatePassword(MD5Utils.MD5(newPassword), phone);
        //更新数据修改时间
        userMapper.updateGmtModified(LocalDateTime.now(), phone);
        return "更改新密码成功";
    }

    /**
     * 用户找回密码
     *
     * @param retrievePasswordVO
     * @return
     */
    @Override
    public String retrievePassword(RetrievePasswordVO retrievePasswordVO) {
        //获得手机号和验证码
        String phone = retrievePasswordVO.getPhone();
        String code = retrievePasswordVO.getCode();

        if (phone == null || code == null) {
            throw new ServiceException(State.ERR_NOT_FOUND, "手机号和验证码都不能为空");
        }

        //判断用户是否存在
        if (isValidMobiNumber(phone)) {
            if (userMapper.selectUser(phone) == null) {
                throw new ServiceException(State.ERR_BAD_REQUEST, "该账号不存在,请先注册再进行操作");
            }
        } else {
            throw new ServiceException(State.ERR_NOT_FOUND, "该手机号不合法");
        }

        if (!code.equals(redisTemplate.opsForValue().get(phone))) {
            throw new ServiceException(State.ERR_NOT_FOUND, "验证码输入错误");
        }
        //重置用户密码为123456
        userMapper.updatePassword(MD5Utils.MD5("123456"), phone);
        //更新数据修改时间
        userMapper.updateGmtModified(LocalDateTime.now(), phone);
        return "密码:123456";
    }

    /**
     * 获取登录时客户端的真实ip
     *
     * @param request
     * @return
     */
    private String getIpAddr(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }

        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
            if (ip.equals("127.0.0.1")) {
                //根据网卡取本机配置的IP
                InetAddress inet = null;
                try {
                    inet = InetAddress.getLocalHost();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                ip = inet.getHostAddress();
            }
        }
        // 多个代理的情况，第一个IP为客户端真实IP,多个IP按照','分割
        if (ip != null && ip.length() > 15) {
            if (ip.indexOf(",") > 0) {
                ip = ip.substring(0, ip.indexOf(","));
            }
        }
        return ip;
    }
}
